'''
Function:
    CVE-2019-7609
Author:
    花果山
Wechat official account：
    中龙 红客突击队
Official website：
    https://www.hscsec.cn/
Email：
    spmonkey@hscsec.cn
Blog:
    https://spmonkey.github.io/
GitHub:
    https://github.com/spmonkey/
'''
# -*- coding: utf-8 -*-
import re
import requests
import os
import sys
from urllib.parse import urlparse
from requests.packages.urllib3 import disable_warnings
disable_warnings()
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
from modules import get_user_agent


class poc:
    def __init__(self, url, proxies):
        self.url = url
        self.headers_version = {
            'User-Agent': get_user_agent.get_user_agent(),
            'Referer': self.url
        }
        self.headers_vuln = {
            'User-Agent': get_user_agent.get_user_agent(),
            'Content-Type': 'application/json;charset=utf-8',
            'Referer': url,
        }
        self.result_text = ""
        self.proxies = proxies

    def host(self):
        url = urlparse(self.url)
        netloc = url.netloc
        scheme = url.scheme
        return scheme, netloc

    def get_kibana_version(self, scheme, netloc):
        url = "{}://{}/app/kibana".format(scheme, netloc)
        try:
            r = requests.get(url=url, headers=self.headers_version, verify=False, proxies=self.proxies)
            patterns = ['&quot;version&quot;:&quot;(.*?)&quot;,', '"version":"(.*?)",']
            for pattern in patterns:
                match = re.findall(pattern, r.text)
                if match:
                    return match[0]
                else:
                    return '9.9.9'
        except:
            return '9.9.9'

    def vuln(self, scheme, netloc, version):
        url = "{}://{}/api/timelion/run".format(scheme, netloc)
        self.headers_vuln['kbn-version'] = version
        data = '{"sheet":[".es(*)"],"time":{"from":"now-1m","to":"now","mode":"quick","interval":"auto","timezone":"Asia/Shanghai"}}'
        try:
            result = requests.post(url=url, data=data, headers=self.headers_vuln, verify=False, proxies=self.proxies)
            if result.status_code == 200 and 'application/json' in result.headers.get('content-type', '') and '"seriesList"' in result.text:
                target = urlparse(url)
                self.result_text += """\n        [+]    \033[32m检测到目标站点存在远程代码执行漏洞 (CVE-2019-7609)\033[0m
                     POST {} HTTP/1.1
                     Host: {}""".format(target.path, target.netloc)
                for request_type, request_text in dict(result.request.headers).items():
                    self.result_text += "\n                 {}: {}".format(request_type, request_text)
                self.result_text += "\n\n                 {}".format(data)
                return True
            else:
                return False
        except:
            return False

    def version_to_tuple(self, version_str):
        return tuple(map(int, version_str.split('.')))

    def main(self):
        all = self.host()
        scheme = all[0]
        netloc = all[1]
        version = self.get_kibana_version(scheme, netloc)
        version_tuple = self.version_to_tuple(version)
        if self.version_to_tuple("5.6.15") <= version_tuple <= self.version_to_tuple("6.6.1"):
            if self.vuln(scheme, netloc, version):
                 return self.result_text
            else:
                return False
        else:
            return False


